package org.hawk.gwt.ppc.reflect.lang;

import org.hawk.gwt.ppc.reflect.emul.java.lang.reflect.GenericDeclaration;
import org.hawk.gwt.ppc.reflect.emul.java.lang.reflect.Type;
import org.hawk.gwt.ppc.reflect.emul.java.lang.reflect.TypeVariable;

/**
 * Implementation for {@link TypeVariable} 
 * @author alex.bereznevatiy@gmail.com
 *
 * @param <D>
 */
public final class GWTTypeVariable<D extends GenericDeclaration> implements TypeVariable<D> {
	
	private String name;
	private Object[] bounds;
	private GenericDeclaration declarator;

	GWTTypeVariable(Object accessor, GenericDeclaration declarator, String name, Object[] bounds) {
		GWTParameterizedType.checkAccess(accessor);
		this.name = name;
		this.declarator = declarator;
		this.bounds = bounds;
	}

	public Type[] getBounds() {
		Type[] result = new Type[bounds.length];
		for (int i = 0; i < bounds.length; i++) {
			if (bounds[i] instanceof Class) {
				result[i] = ClassDelegate.forClass((Class<?>)bounds[i]);
			} else {
				result[i] = (Type)bounds[i];
			}
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	public D getGenericDeclaration() {
		return (D) declarator;
	}

	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return name;
	}

	@Override
	public int hashCode() {
		return 31 * declarator.hashCode() + name.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || !(obj instanceof GWTTypeVariable)) {
			return false;
		}

		@SuppressWarnings("unchecked")
		GWTTypeVariable<D> other = (GWTTypeVariable<D>) obj;
		return name.equals(other.name) && declarator.equals(other.declarator);
	}
}
